#pragma once

template <typename T>
struct BaseWindow
{
	static T * GetThisFromHandle(HWND window)
	{
		return reinterpret_cast<T *>(GetWindowLongPtr(window, GWLP_USERDATA));
	}

	static LRESULT __stdcall WndProc(HWND const window,
							  UINT const message, 
							  WPARAM const wparam, 
							  LPARAM const lparam)
	{
		if (message == WM_NCCREATE)
		{
			auto cs = reinterpret_cast<CREATESTRUCT*>(lparam);
			T * that = static_cast<T *>(cs->lpCreateParams);

			ASSERT(that);
			ASSERT(!that->m_window);

			that->m_window = window;

			SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
		}
		else if (T * that = GetThisFromHandle(window))
		{
			return that->MessageHandler(message, wparam, lparam);
		}

		return DefWindowProc(window, message, wparam, lparam);
	}

	LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam)
	{
		if (message == WM_DESTROY)
		{
			PostQuitMessage(0);
		}

		return DefWindowProc(m_window, message, wparam, lparam);
	}

	HWND m_window = nullptr;
};